package node;

import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.util.Arrays;
import java.util.Scanner;

import log.Logger;
/**
 * This class is the landing point for new actual node adding.
 *  This will interactively ask the user for the node to add.
 * @author Team4
 * @version Spring 2013
 *
 */
public final class LaunchAddNode
{
  /**
   * Registry name.
   */
  private String remote_registry = "RemoteRegistry";
  /**
   * Host name.
   */
  private String hostname;
  /**
   * port number.
   */
  private int port;
  /**
   * Private constructor to prevent instantiation.
   */
  public LaunchAddNode(String host, int port, String remote)
  {
    this.hostname = host;
    this.port = port;
    this.remote_registry = remote;
  }
  /**
   * This static method is called from the NodeManager that will initialize all the
   * variables in the NodeManager and add the new node information to it.
   * The new node also exists alongside the old node in the rmi registry 
   * with different names.
   */
  public void Adding_Node() 
  {
    try
    {
      System.out.println(" list of nodes currently in the registry are  " +
          Arrays.toString(NodeManager.registry.list()));
      System.out.println(" Select a number for the  actual node to add  - ");
      final Scanner scanner = new Scanner(System.in);
      String node_name = scanner.nextLine();
      if (node_name.trim().isEmpty())
      {
        System.out.println("Hmm, I didn't get node name");
        System.exit(1);
      }
      if (node_name.trim().endsWith("V") || node_name.trim().endsWith("A"))
      {
        node_name = node_name.substring(0, node_name.length() - 1);
      }
      final int node_num = Integer.parseInt(node_name);
      if (this.rmi_NodeFind(node_num).endsWith("A"))
      {
        System.out.println(" please give a number that is not taken by a actual node ");
        System.exit(1);
      }
      
      final NodeManager nm = 
          new NodeManager(this.hostname, this.port, this.remote_registry);
      nm.actual_node_number = node_num;
      nm.LOGGER_FILE_NAME = "LOG-" + nm.actual_node_number + ".txt";  
      nm.total_nodes_chord = NodeManager.registry.list().length;
      Logger.writeContent(nm.LOGGER_FILE_NAME, " the node " +
          node_num + " is going to be added to the chord.");
      Logger.out(" the node " + node_num + " is going to be added to the chord.");
      Logger.writeContent(nm.LOGGER_FILE_NAME, 
                          "the total nodes in the current chord is " + 
                           NodeManager.total_nodes_chord);
      nm.remoteObjectCreation(node_num, nm.HOST, nm.PORT, 
                                       nm.REMOTE);
      Logger.out(" List of nodes temporarily in registry are - " +
          Arrays.toString(NodeManager.registry.list()));
      Logger.writeContent(nm.LOGGER_FILE_NAME, 
                          " List of nodes temporarily in registry are - " +
          Arrays.toString(NodeManager.registry.list()));
      nm.messageChannelSetup(0);
      nm.QueueThreadStart(0);
      final NodeAddition new_nodes = new NodeAddition(node_num,nm);
      new_nodes.addActualNode();
      
      final String unbind = new Integer(node_num).toString() + "V";
      NodeManager.registry.unbind(unbind);
      
    }
    catch (final RemoteException e)
    {
      Logger.err("A problem occurred: " + e);
      System.exit(1);
    }
    
    catch (final NotBoundException e)
    {
      Logger.err("Problem" + e);
      System.exit(1);
    }
    
  }
  /**
   * Given a node number this method will find its rmi name in registry by appending
   * a V or a A to it corresponding to actual/virtual.
   * @return String - the registry name for this node number.
   */
  public String rmi_NodeFind(final int node_num) 
  {
    final String rmi_name_actual = new Integer(node_num).toString() + "A";
    final String rmi_name_virtual = new Integer(node_num).toString() + "V";
    try
    {
      if (NodeManager.registry.lookup(rmi_name_actual) == null)
      {
        return rmi_name_virtual;
      }
      else
      {
        return rmi_name_actual;
      }
    }
    catch (final RemoteException | NotBoundException e)
    {
     // Logger.writeContent(LOGGER_FILE_NAME, 
       //                   " Remote exception occured or the given name is not bound " + e);
      System.exit(1);
    }
    return rmi_name_virtual;
  }
}
